package com.zhxq.member.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.BCrypt;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zhxq.common.core.domain.AjaxResult;
import com.zhxq.common.utils.StringUtils;
import com.zhxq.framework.web.service.TokenService;
import com.zhxq.member.domain.Member;
import com.zhxq.member.domain.dto.UserLoginDto;
import com.zhxq.member.domain.dto.WxLoginDto;
import com.zhxq.member.domain.vo.LoginVo;
import com.zhxq.member.mapper.MemberMapper;
import com.zhxq.member.properties.WxProperties;
import com.zhxq.member.service.IMemberService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 客户 服务实现类
 * </p>
 *
 * @author zxs
 * @since 2025-06-13
 */
@Service
@RequiredArgsConstructor
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements IMemberService {

    private final WxProperties wxProperties;

    private final TokenService tokenService;

    // 登录
    private static final String REQUEST_URL = "https://api.weixin.qq.com/sns/jscode2session?grant_type=authorization_code";

    // 获取token
    private static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";

    // 获取手机号
    private static final String PHONE_REQUEST_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=";

    static List<String> DEFAULT_NICK_NAME = ListUtil.of(
            "切图仔",
            "程序猿",
            "CV工程师",
            "高级牛马",
            "码农",
            "java炒饭",
            "python炒粉",
            "产品经理个傻*"
    );

    /**
     * 微信登录
     * @param wxLoginDto
     * @return
     */
    @Override
    public AjaxResult wxLogin(WxLoginDto wxLoginDto) {
        //1.获取openid(调用微信的接口获取) ***
        String openId = getOpenId(wxLoginDto.getCode());
        //2.根据openid查询用户
        LambdaQueryWrapper<Member> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Member::getOpenId, openId);
        Member member = getOne(queryWrapper);
        //3.判断用户是否存在，用户不存在，就构建用户
        if(ObjectUtil.isEmpty(member)) {
            member = new Member();
            member.setOpenId(openId);
        }
        //4.获取用户的手机号（调用微信的接口获取）***
        String phone = getPhone(wxLoginDto.getPhoneCode());
        //5. 新增或修改用户
        saveOrUpdate(member, phone);
        //6. 把用户的信息封装到token,返回
        Map<String, Object> claims = new HashMap<>();
        claims.put("username", member.getUsername());
        claims.put("userId", member.getId());
        String token = tokenService.createToken(claims);
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token);
        loginVo.setNickName(member.getNickName());
        return AjaxResult.success(loginVo);
    }

    @Override
    public AjaxResult userLogin(UserLoginDto userLoginDto) {
        String username = userLoginDto.getUsername();
        LambdaQueryWrapper<Member> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Member::getUsername, username);
        Member member = getOne(queryWrapper);
        if(ObjectUtil.isEmpty(member)) {
            throw new RuntimeException("用户不存在");
        }
        if(!BCrypt.checkpw(userLoginDto.getPassword(), member.getPassword())) {
            throw new RuntimeException("密码错误");
        }
        Map<String, Object> claims = new HashMap<>();
        claims.put("username", member.getUsername());
        claims.put("userId", member.getId());
        String token = tokenService.createToken(claims);
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token);
        loginVo.setNickName(member.getNickName());
        return AjaxResult.success(loginVo);
    }

    /**
     * 新增或修改用户
     * @param member
     * @param phone
     */
    private void saveOrUpdate(Member member, String phone) {
        //1.判断取到的手机号与数据库中保存的手机号是否一样
        if(ObjectUtil.notEqual(member.getPhone(), phone)) {
            member.setPhone(phone);
        }
        //2.判断id存在
        if(ObjectUtil.isNotEmpty(member.getId())) {
            updateById(member);
            return;
        }
        String nickName = DEFAULT_NICK_NAME.get((int) (Math.random() * DEFAULT_NICK_NAME.size()))
                + StringUtils.substring(member.getPhone(), 7);
        String datePrefix = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
        String phoneSuffix = phone.substring(phone.length() - 4);
        member.setUsername(datePrefix + phoneSuffix);
        member.setNickName(nickName);
        String password = BCrypt.hashpw(phone, BCrypt.gensalt());
        member.setPassword(password);
        save(member);
    }

    /**
     * 封装公共参数
     * @return
     */
    private Map<String, Object> getAppConfig() {

        Map<String, Object> requestUrlParam = new HashMap<>();
        requestUrlParam.put("appid",wxProperties.getAppid());
        requestUrlParam.put("secret",wxProperties.getSecret());
        return requestUrlParam;
    }

    /**
     * 获取微信openId
     * @param code
     * @return
     */
    private String getOpenId(String code) {
        Map<String,Object> requestUrlParam = getAppConfig();
        requestUrlParam.put("js_code", code);
        String str = HttpUtil.get(REQUEST_URL, requestUrlParam);
        JSONObject jsonObject = JSONUtil.parseObj(str);
        if(ObjectUtil.isNotEmpty(jsonObject.getInt("errcode"))) {
            throw new RuntimeException(jsonObject.getStr("errmsg"));
        }
        return jsonObject.getStr("openid");
    }

    /**
     * 获取token
     * @return
     */
    private String getToken() {
        Map<String, Object> requestUrlParam = getAppConfig();
        requestUrlParam.put("grant_type", "client_credential");
        String str = HttpUtil.get(TOKEN_URL, requestUrlParam);
        JSONObject jsonObject = JSONUtil.parseObj(str);
        //如果code不正确，则失败
        if(ObjectUtil.isNotEmpty(jsonObject.getInt("errcode"))){
            throw new RuntimeException(jsonObject.getStr("errmsg"));
        }
        return jsonObject.getStr("access_token");
    }

    /**
     * 获取手机号
     * @param phoneCode
     * @return
     */
    private String getPhone (String phoneCode) {
        String url = PHONE_REQUEST_URL + getToken();
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("code", phoneCode);
        String str = HttpUtil.post(url, JSONUtil.toJsonStr(paramMap));
        JSONObject jsonObject = JSONUtil.parseObj(str);
        if(jsonObject.getInt("errcode") != 0) {
            throw new RuntimeException(jsonObject.getStr("errmsg"));
        }
        return jsonObject.getJSONObject("phone_info").getStr("phoneNumber");
    }
}
